package com.example.stringbufferlogger.Utils;

import com.example.stringbufferlogger.VO.ComparisonResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.util.*;

public class DataComparator {

    private static final ObjectMapper jsonMapper = new ObjectMapper();
    private static final XmlMapper xmlMapper = new XmlMapper();

    public enum DataFormat {
        JSON, XML
    }

    /**
     * 比较两个数据（JSON 或 XML），返回结构化差异
     */
    public static ComparisonResult compareData(
            String data1, String data2,
            DataFormat format1, DataFormat format2,
            Set<String> ignoredFields) {

        ComparisonResult result = new ComparisonResult();
        try {
            JsonNode node1 = parseData(data2, format2);
            JsonNode node2 = parseData(data1, format1);

            compareNodes(node1, node2, ignoredFields, "", result);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage("解析数据时出错: " + e.getMessage());
        }
        return result;
    }

    /**
     * 自动识别输入内容是 JSON 还是 XML 格式
     */
    public static DataFormat detectFormat(String content) {

        if (content == null || content.isEmpty()) {
            throw new IllegalArgumentException("输入内容不能为空");
        }

        content = content.trim();
        if (content.startsWith("{") || content.startsWith("[")) {
            return DataFormat.JSON;
        } else if (content.startsWith("<")) {
            return DataFormat.XML;
        } else {
            throw new IllegalArgumentException("无法识别的数据格式");
        }
    }

    /**
     * 解析指定格式的数据为 JsonNode
     */
    private static JsonNode parseData(String content, DataFormat format) throws JsonProcessingException {
        switch (format) {
            case JSON:
                return jsonMapper.readTree(content);
            case XML:
                return xmlMapper.readTree(content);
            default:
                throw new IllegalArgumentException("不支持的数据格式: " + format);
        }
    }

    /**
     * 递归比较两个节点
     */
    private static void compareNodes(JsonNode node1, JsonNode node2, Set<String> ignoredFields, String path, ComparisonResult result) {
        if (node1.isObject() && node2.isObject()) {
            handleObjectNodes(node1, node2, ignoredFields, path, result);
        } else if (node1.isArray() && node2.isArray()) {
            handleArrayNodes(node1, node2, path, result);
        } else {
            if (!node1.equals(node2)) {
                recordDifference(path, node1, node2, result);
            }
        }
    }

    private static void handleObjectNodes(JsonNode obj1, JsonNode obj2, Set<String> ignoredFields, String path, ComparisonResult result) {
        Set<String> allFields = new HashSet<>();
        obj1.fieldNames().forEachRemaining(allFields::add);
        obj2.fieldNames().forEachRemaining(allFields::add);

        for (String field : allFields) {
            if (ignoredFields.contains(field)) continue;

            JsonNode child1 = obj1.get(field);
            JsonNode child2 = obj2.get(field);
            String newPath = path.isEmpty() ? field : path + "." + field;

            if (child1 == null || child2 == null) {
                recordDifference(newPath, child1, child2, result);
            } else {
                compareNodes(child1, child2, ignoredFields, newPath, result);
            }
        }
    }

    private static void handleArrayNodes(JsonNode array1, JsonNode array2, String path, ComparisonResult result) {
        int size = Math.min(array1.size(), array2.size());

        for (int i = 0; i < size; i++) {
            compareNodes(array1.get(i), array2.get(i), Collections.emptySet(), path + "[" + i + "]", result);
        }
    }

    private static void recordDifference(String path, JsonNode oldNode, JsonNode newNode, ComparisonResult result) {
        Map<String, Object> difference = new LinkedHashMap<>();
        difference.put("oldRes", oldNode != null ? oldNode.toString() : null);
        difference.put("newRes", newNode != null ? newNode.toString() : null);
        result.getDifferences().put(path, difference);
    }

    public static void main(String[] args) {
        Set<String> ignoredFields = new HashSet<>();
        // 示例 XML 数据
        String xmlA = "<Response><status>fail</status><data><id>1002</id><name>Alice</name></data></Response>";
        String xmlB = "<Response><status>success</status><data><id>1001</id><name>Alice</name></data></Response>";

        // 测试你提供的两个 XML 对比
        System.out.println("=== 测试你提供的 XML 对比 ===");
        testCompare(xmlA, xmlB, DataFormat.XML, DataFormat.XML, ignoredFields);

        // 测试自动识别格式的版本
        System.out.println("\n=== 测试自动识别 XML 对比 ===");
        testCompareAuto(xmlA, xmlB, ignoredFields);

        // 测试忽略字段 data.id
        System.out.println("\n=== 测试忽略字段 data.id ===");
        testCompareAuto(xmlA, xmlB, ignoredFields);
    }

    private static void testCompare(String data1, String data2, DataFormat format1, DataFormat format2, Set<String> ignoredFields) {
        try {
            ComparisonResult result = compareData(data1, data2, format1, format2, ignoredFields);
            if (!result.isSuccess()) {
                System.err.println("错误信息：" + result.getErrorMessage());
            } else if (result.isDifferences()) {
                System.out.println("存在差异:");
                System.out.println(result.getDifferencesStr());
            } else {
                System.out.println("无差异");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testCompareAuto(String data1, String data2, Set<String> ignoredFields) {
        try {
            DataFormat format1 = detectFormat(data1);
            DataFormat format2 = detectFormat(data2);
            ComparisonResult result = compareData(data1, data2, format1, format2, ignoredFields);
            if (!result.isSuccess()) {
                System.err.println("错误信息：" + result.getErrorMessage());
            } else if (result.isDifferences()) {
                System.out.println("存在差异:");
                System.out.println(result.getDifferencesStr());
            } else {
                System.out.println("无差异");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
